﻿using System;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Collections.Concurrent;
using System.Xml.Serialization;
using System.Collections.Generic;
using DiPlaner.Properties;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using System.Security.Permissions;

[assembly: RegistryPermissionAttribute(SecurityAction.RequestMinimum,
    ViewAndModify = "HKEY_CURRENT_USER")]

namespace DiPlaner
{
    public partial class DiForm : Form
    {

        #region VARIABLES

        public static string LastLogSMG = "";

        public static SynchronizationContext main_context = new SynchronizationContext();

        public static WorkerClass Worker = new WorkerClass();

        public static Profile CurentProfile = new Profile();

        public Stopwatch sw = new Stopwatch();
        public Stopwatch delayTimer = new Stopwatch();

        private Stopwatch SpanTimer = new Stopwatch();
        private List<Profile.BotStart> DummyBotStart = new List<Profile.BotStart>();
        
        private int idleCount = 0;

        private bool firstStart = false;
        private bool dummyStart = false;

        public int CheckCounter = 0;

        public static int SelectedPlan = 0;

        public static volatile bool CheckAllow = true;

        public static bool Hooked = false;

        #endregion

        

        #region DiForm

        public DiForm()
        {
            InitializeComponent();
            CurentProfile = CurentProfile.Initialize();

            this.FormClosed += new FormClosedEventHandler(ActiveForm_FormClosed);

            main_context = SynchronizationContext.Current;
            if (main_context == null)
            {
                main_context = new SynchronizationContext();
            }

            Settings.Default.Upgrade();
            cb_step.SelectedIndex = Settings.Default.Set;
            if (Settings.Default.ProfileList != null)
                for (int i = 0; Settings.Default.ProfileList.Count > i && i <= 10; i++)
                {
                    if (File.Exists(Settings.Default.ProfileList[i]))
                        CB_Profile.Items.Add(Settings.Default.ProfileList[i]);
                }
            if (Settings.Default.LastProfile != null && CB_Profile.Items.Contains(Settings.Default.LastProfile)) CurentProfile = LoadProfile(Settings.Default.LastProfile);

            timer.Start();

        }

        private void DiForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer.Stop();
            Worker.StopWork();
            Program.StopHook();
        }

        void ActiveForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Settings.Default.Set = cb_step.SelectedIndex;
            Settings.Default.LastProfile = (string)CB_Profile.SelectedItem;
            if (CB_Profile.Items != null && CB_Profile.Items.Count > 0)
            {
                Settings.Default.ProfileList = new System.Collections.Specialized.StringCollection();
                foreach (string path in CB_Profile.Items) Settings.Default.ProfileList.Add(path);
            }
            Settings.Default.Save();
        }

        #endregion



        #region UI LOG

        private void bt_openlog_Click(object sender, EventArgs e)
        {
            Process proc = new Process();
            proc.StartInfo.FileName = tb_logfile.Text;
            proc.Start();
            proc.Dispose();
        }

        private void bt_log_Click(object sender, EventArgs e)
        {
            if (DiForm.ActiveForm.Size.Width <= 300)
            {
                DiForm.ActiveForm.Size = new Size(650, 480);
                return;
            }
            if (DiForm.ActiveForm.Size.Width >= 620) DiForm.ActiveForm.Size = new Size(290, 480);
        }
        #endregion



        #region UI EVENTS

        private void BT_ProfileBrowse_Click(object sender, EventArgs e)
        {
            openFile.Filter = "Profile|*.xml";
            openFile.Title = "Select profile";
            openFile.ShowDialog();
            string path = openFile.FileName;
            if (path.Length > 0)
            {
                CurentProfile = LoadProfile(path);
            }
        }

        private void cb_step_SelectedIndexChanged(object sender, EventArgs e)
        {
            GenerateSchedule(DateTime.Now);
            BotActiveSwitcher(CurentProfile.WorkPlan.Schedule.Count);
            CheBotSlots();
            Slot_UI_Switcher(true);
            SelectedPlan = cb_step.SelectedIndex;
        }

        private void CB_Profile_SelectedIndexChanged(object sender, EventArgs e)
        {
            CurentProfile = LoadProfile((string)((ComboBox)sender).SelectedItem);
            CheBotSlots();
        }

        private void CB_Profile_Format(object sender, ListControlConvertEventArgs e)
        {
            try
            {
                e.Value =Path.GetFileName(e.Value.ToString());
            }
            catch (ArgumentException) { }
        }

        private void BotActiveSwitcher(int bots)
        {
            for (int i = 1; i <= bots; i++)
            {
                ((Panel)GetControlByName("pan_bot_" + i)).Visible = true;
            }
            for (int i = 8; i > bots; i--)
            {
                ((Panel)GetControlByName("pan_bot_" + i)).Visible = false;
            }
        }

        private void track_span_Scroll(object sender, EventArgs e)
        {
            SpanTimer.Reset();
            SpanTimer.Start();
            Slot_UI_Switcher(false);

            string mn = "";
            if ((int)(track_span.Value) > 0) mn = "-";
            else mn = "";
            tb_span.Text = mn + (int)(track_span.Value) + "h";


            GenerateSchedule(DateTime.Now - new TimeSpan(track_span.Value, 0, 0));

            firstStart = false;


        }

        private void bt_Clear_Click(object sender, EventArgs e)
        {
            CurentProfile = new Profile();
            CurentProfile.Bots = new List<Profile.BotProfile>();
            for (int i = 0; i < 8; i++)
            {
                CurentProfile.Bots.Add(new Profile.BotProfile()
                {
                    bnet = "",
                    d3_path = "",
                    db_key = "",
                    db_path = "",
                    db_routine = "",
                    pass = "",
                    pos = new Point(0, 0),
                    ready = false,
                    size = new Size(150, 90),
                    slot = i,
                    status = Profile.BotStatus.idle
                });
            }
            CurentProfile.Path = "_temp.tmp";
            SaveProfile();
            LoadProfile("_temp.tmp");
            CB_Profile.Items.Clear();
            cb_step.SelectedIndex = 0;
        }

        private void notIcon_DoubleClick(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Show();
                this.WindowState = FormWindowState.Normal;
                this.ShowInTaskbar = true;
                notIcon.Visible = false;
            }
        }

        private void DiForm_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
                this.ShowInTaskbar = false;
                notIcon.Visible = true;
            }
        }

        private void Bot_min_Click(object sender, EventArgs e)
        {
            Button sndr = (Button)sender;
            int pos = Convert.ToInt16(sndr.Name.Substring(11, 1));
            Program._moveWindow(pos);

            ((Button)GetControlByName("bt_bot_min_" + pos)).Enabled = false;
            ((Button)GetControlByName("bt_bot_norm_" + pos)).Enabled = true;
        }

        private void Bot_norm_Click(object sender, EventArgs e)
        {
            Button sndr = (Button)sender;
            int pos = Convert.ToInt16(sndr.Name.Substring(12, 1));
            Program._restoreWindow(pos);

            ((Button)GetControlByName("bt_bot_min_" + pos)).Enabled = true;
            ((Button)GetControlByName("bt_bot_norm_" + pos)).Enabled = false;

        }

        #endregion



        #region PROFILE FUNCTIONS

        public void GenerateSchedule(DateTime starDate)
        {
            DateTime dt_cur = starDate;
            Profile.BotSchedule BS = new Profile.BotSchedule();
            BS.Schedule = new List<Profile.BotStart>();

            int delay = 0;
            int worktime = 0;
            int after_start = 0;
            int slots = 0;
            switch (cb_step.SelectedIndex)
            {
                #region [1 / 1] 18h /  6h
                case 0:
                    delay = 6;
                    worktime = 18;
                    after_start = 0;
                    slots = 1;
                    break;
                #endregion
                #region [1 / 2] 12h / 12h
                case 1:
                    delay = 12;
                    worktime = 12;
                    after_start = 12;
                    slots = 2;
                    break;
                #endregion
                #region [2 / 3] 12h /  6h
                case 2:
                    delay = 6;
                    worktime = 12;
                    after_start = 6;
                    slots = 3;
                    break;
                #endregion
                #region [2 / 4] 12h / 12h
                case 3:
                    delay = 12;
                    worktime = 12;
                    after_start = 6;
                    slots = 4;
                    break;
                #endregion
                #region [3 / 4] 18h /  6h
                case 4:
                    delay = 6;
                    worktime = 18;
                    after_start = 6;
                    slots = 4;
                    break;
                #endregion
                #region [3 / 6] 18h / 18h
                case 5:
                    delay = 18;
                    worktime = 18;
                    after_start = 6;
                    slots = 6;
                    break;
                #endregion
                #region [4 / 6] 24h / 12h
                case 6:
                    delay = 12;
                    worktime = 24;
                    after_start = 6;
                    slots = 6;
                    break;
                #endregion
                #region [4 / 8] 24h / 24h
                case 7:
                    delay = 24;
                    worktime = 24;
                    after_start = 6;
                    slots = 8;
                    break;
                #endregion
                #region [5 / 7] 30h / 12h
                case 8:
                    delay = 12;
                    worktime = 30;
                    after_start = 6;
                    slots = 7;
                    break;
                #endregion
                #region [6 / 8] 18h /  6h
                case 9:
                    delay = 6;
                    worktime = 18;
                    after_start = 3;
                    slots = 8;
                    break;
                #endregion
            }
            BS.Delay = new TimeSpan(delay, 0, 0);
            BS.workTime = new TimeSpan(worktime, 0, 0);
            if (slots != 1) dt_cur += new TimeSpan(-(worktime - after_start), 0, 0);
            for (int i = 1; i <= slots; i++)
            {
                BS.Schedule.Add(new Profile.BotStart()
                {
                    flagtime = new DateTime(),
                    pauseflag = new DateTime(),
                    startTime = dt_cur,
                    stopTime = dt_cur.Add(BS.workTime),
                    status = Profile.BotStatus.stop,
                });
                dt_cur += new TimeSpan(after_start, 0, 0);
            }
            CurentProfile.WorkPlan = new Profile.BotSchedule();
            CurentProfile.WorkPlan = BS;

        }

        private void Scheduler(Profile.BotStatus status = Profile.BotStatus.idle)
        {
            if (!sw.IsRunning) return;

            this.Text = "Di Planer" + string.Format(" [Runing {0:0}:{1:00}:{2:00}:{3:00}]", sw.Elapsed.Days, sw.Elapsed.Hours, sw.Elapsed.Minutes, sw.Elapsed.Seconds);

            for (int i = 0; i < CurentProfile.WorkPlan.Schedule.Count; i++)
            {
                Profile.BotStart BS = CurentProfile.WorkPlan.Schedule[i];

                if (status != Profile.BotStatus.idle) BS.status = status;
                else if (BS.status != Profile.BotStatus.paused && BS.status != Profile.BotStatus._resuming && BS.status != Profile.BotStatus.idle && BS.status != Profile.BotStatus.crashed)
                {
                    if (BS.startTime.Add(CurentProfile.WorkPlan.workTime - (new TimeSpan(0, 5, 0))) <= DateTime.Now)
                        BS.status = Profile.BotStatus._stoping;
                    else if (BS.startTime <= DateTime.Now && BS.status != Profile.BotStatus.running)
                        BS.status = Profile.BotStatus._starting;
                }
                
                TimeSpan elts;
                switch (BS.status)
                {
                    case Profile.BotStatus._stoping:        //Pre-Stoping

                            if (!firstStart)
                            {
                                BS.flagtime = DateTime.Now;
                                BS.startTime = BS.stopTime + CurentProfile.WorkPlan.Delay;
                                BS.stopTime = BS.startTime + CurentProfile.WorkPlan.workTime;
                                BS.status = Profile.BotStatus.stop;
                                break;
                            }

                            BS.flagtime = DateTime.Now;
                            BS.startTime = BS.stopTime + CurentProfile.WorkPlan.Delay;
                            BS.stopTime = BS.startTime + CurentProfile.WorkPlan.workTime;

                        ((Label)GetControlByName("timer_" + (i + 1))).Text = "0:00:00:00";

                        // ########## [STOP] ###########

                        DiRunTime.StopSlot(i);

                        // #############################

                        BS.status = Profile.BotStatus.stop;
                        break;

                    case Profile.BotStatus.stop:            //Stoped
                        
                        elts = (BS.startTime - DateTime.Now);

                        ((Label)GetControlByName("timer_" + (i + 1))).ForeColor = Color.Red;
                        ((Label)GetControlByName("timer_" + (i + 1))).Text = string.Format("{0:0}:{1:00}:{2:00}:{3:00}", elts.Days, elts.Hours, elts.Minutes, elts.Seconds);

                        ((Button)GetControlByName("bt_bot_min_" + (i + 1))).Enabled = false;
                        ((Button)GetControlByName("bt_bot_norm_" + (i + 1))).Enabled = false;

                        break;

                    case Profile.BotStatus._pausing:        //Pre-Pause

                        DiForm.Worker.LogTask("--Pausing Bot #" + (i + 1) + " for 15 min");
                        
                        BS.pauseflag = DateTime.Now;

                        ((Label)GetControlByName("timer_" + (i + 1))).ForeColor = Color.Blue;
                        ((Label)GetControlByName("timer_" + (i + 1))).Text = "0:00:00:00";

                        ((Button)GetControlByName("bt_bot_min_" + (i + 1))).Enabled = false;
                        ((Button)GetControlByName("bt_bot_norm_" + (i + 1))).Enabled = false;

                        // ######### [PAUSE] ###########

                        DiRunTime.ClickStartStop(i);

                        // #############################

                        BS.status = Profile.BotStatus.paused;
                        break;

                    case Profile.BotStatus.paused:          //Paused

                            elts = DateTime.Now - BS.pauseflag;

                            ((Label)GetControlByName("timer_" + (i + 1))).Text = string.Format("{0:0}:{1:00}:{2:00}:{3:00}", elts.Days, elts.Hours, elts.Minutes, elts.Seconds);

                        if ((int)elts.TotalSeconds >= 15) BS.status = Profile.BotStatus.idle;
                        break;

                    case Profile.BotStatus._resuming:       //Pre-Resume

                            elts = DateTime.Now - BS.pauseflag;
                            DiForm.Worker.LogTask("++Resuming Bot #" + (i + 1) + " after " + string.Format("{0:00}m {1:00}s", elts.Minutes, elts.Seconds));
                        
                        // ######### [RESUME] ##########

                        DiRunTime.ClickStartStop(i);

                        // #############################

                        BS.status = Profile.BotStatus.stop;
                        break;
                    #region Starting
                    case Profile.BotStatus._starting:       //Pre-Start
                        
                        ((Label)GetControlByName("timer_" + (i + 1))).ForeColor = Color.Green;

                        ((Button)GetControlByName("bt_bot_min_" + (i + 1))).Enabled = false;
                        ((Button)GetControlByName("bt_bot_norm_" + (i + 1))).Enabled = true;

                        // ########## [START] ##########

                        DiRunTime.RunSlot(i);

                        // #############################

                        BS.status = Profile.BotStatus.running;
                        break;
                    #endregion

                    case Profile.BotStatus.running:         //Started
                        
                            elts = DateTime.Now - BS.startTime;

                            ((Label)GetControlByName("timer_" + (i + 1))).Text = string.Format("{0:0}:{1:00}:{2:00}:{3:00}", elts.Days, elts.Hours, elts.Minutes, elts.Seconds);

                        // ####### [CHECK STATE] #######
                        //*
                            if (!delayTimer.IsRunning) delayTimer.Start();
                            if (delayTimer.Elapsed.TotalSeconds > 60 && CheckAllow)
                            {
                                DiRunTime.CheckSlot(CheckCounter);
                                CheckCounter++;
                                if (CheckCounter >= CurentProfile.WorkPlan.Schedule.Count) CheckCounter = 0;
                                delayTimer.Reset();
                            }
                        //*/
                        // #############################

                        break;

                    case Profile.BotStatus.idle:

                            idleCount++;
                            if (idleCount >= CurentProfile.WorkPlan.Schedule.Count)
                            {
                                DiForm.Worker.LogTask("Maximum waiting time on pause is over.\r\n"
                                + "Stoping DiPlaner...");
                                bt_stop_Click(null, null);
                            }

                        break;

                    case Profile.BotStatus.crashed:

                        // ######### [CRASHED] #########

                        BS.status = Profile.BotStatus._stoping;

                        // #############################

                        break;
                }
                CurentProfile.WorkPlan.Schedule[i] = BS;
            }
        }

        public Profile LoadProfile(string path)
        {
            Profile profile = new Profile();

            try
            {
                var serializer = new XmlSerializer(typeof(Profile));
                if (File.Exists(path)) using (TextReader reader = new StreamReader(path))
                        profile = (Profile)serializer.Deserialize(reader);

                profile.Path = path;

                if (!CB_Profile.Items.Contains(path))
                    CB_Profile.Items.Add(path);
                CB_Profile.SelectedItem = path;
                cb_step.SelectedIndex = profile.ScheduleSet;
            }
            catch (Exception e)
            {
                MessageBox.Show("Incorrect Profile!\r\n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                CB_Profile.Items.Remove(profile.Path);
                return new Profile();
            }

            return profile;
        }

        public void SaveProfile(bool button = false)
        {
            if (button || (CB_Profile.SelectedItem == null || CB_Profile.SelectedItem.ToString().Length <= 0))
            {
                saveFile.DefaultExt = ".xml";
                saveFile.ShowDialog();
                if (saveFile.FileName.Length >= 3)
                {
                    CurentProfile.Path = saveFile.FileName;
                    CurentProfile.ScheduleSet = cb_step.SelectedIndex;
                    if (!CB_Profile.Items.Contains(CurentProfile.Path))
                        CB_Profile.Items.Add(CurentProfile.Path);
                    Settings.Default.LastProfile = CurentProfile.Path;
                    Settings.Default.ProfileList = new System.Collections.Specialized.StringCollection();
                    if (CB_Profile.Items != null) foreach (string path in CB_Profile.Items) Settings.Default.ProfileList.Add(path);
                }
            }

            if (CurentProfile.Path == null) CurentProfile.Path = System.Reflection.Assembly.GetExecutingAssembly().Location + "_tempProfile.xml";

            var serializer = new XmlSerializer(typeof(Profile));
            if (CurentProfile.Path.Length > 0) using (TextWriter writer = new StreamWriter(CurentProfile.Path))
                {
                    serializer.Serialize(writer, CurentProfile);
                }

            CB_Profile.SelectedItem = CurentProfile.Path;
        }

        public void SetBotNames()
        {
            for (int i = 0; i < 8; i++)
            {
                if (CurentProfile.Bots[i].bnet != null && CurentProfile.Bots[i].bnet.Length > 0 && CurentProfile.Bots[i].bnet.IndexOf("@") > 0)
                    ((Label)GetControlByName("botCharLabel_" + (i + 1))).Text =
                        CurentProfile.Bots[i].bnet.Substring(0, CurentProfile.Bots[i].bnet.IndexOf("@"));
            }
        }

        private void DummyScheduler()
        {
            for (int i = 0; i < CurentProfile.WorkPlan.Schedule.Count; i++)
            {
                Profile.BotStart BS = DummyBotStart[i];

                if (BS.startTime.Add(CurentProfile.WorkPlan.workTime) <= DateTime.Now)
                        BS.status = Profile.BotStatus._stoping;
                else if (BS.startTime <= DateTime.Now && BS.status != Profile.BotStatus.running)
                        BS.status = Profile.BotStatus._starting;

                TimeSpan elts;
                switch (BS.status)
                {
                    case Profile.BotStatus._stoping:        //Pre-Stoping

                        if (!dummyStart)
                        {
                            BS.flagtime = DateTime.Now;
                            BS.startTime = BS.stopTime + CurentProfile.WorkPlan.Delay;
                            BS.stopTime = BS.startTime + CurentProfile.WorkPlan.workTime;
                            BS.status = Profile.BotStatus.stop;
                            break;
                        }

                        BS.flagtime = DateTime.Now;
                        BS.startTime = BS.stopTime + CurentProfile.WorkPlan.Delay;
                        BS.stopTime = BS.startTime + CurentProfile.WorkPlan.workTime;

                        ((Label)GetControlByName("timer_" + (i + 1))).Text = "0:00:00:00";

                        BS.status = Profile.BotStatus.stop;
                        break;


                    case Profile.BotStatus.stop:            //Stoped
                        
                        elts = (BS.startTime - DateTime.Now);

                        ((Label)GetControlByName("timer_" + (i + 1))).ForeColor = Color.Red;
                        ((Label)GetControlByName("timer_" + (i + 1))).Text = string.Format("{0:0}:{1:00}:{2:00}:{3:00}", elts.Days, elts.Hours, elts.Minutes, elts.Seconds);
                        break;


                    case Profile.BotStatus._pausing:        //Pre-Pause
                        
                        BS.pauseflag = DateTime.Now;

                        ((Label)GetControlByName("timer_" + (i + 1))).ForeColor = Color.Blue;
                        ((Label)GetControlByName("timer_" + (i + 1))).Text = "0:00:00:00";

                        BS.status = Profile.BotStatus.paused;
                        break;


                    case Profile.BotStatus.paused:          //Paused
                        
                        elts = DateTime.Now - BS.pauseflag;

                        ((Label)GetControlByName("timer_" + (i + 1))).Text = string.Format("{0:0}:{1:00}:{2:00}:{3:00}", elts.Days, elts.Hours, elts.Minutes, elts.Seconds);

                        if ((int)elts.TotalSeconds >= 15) BS.status = Profile.BotStatus.idle;
                        break;


                    case Profile.BotStatus._resuming:       //Pre-Resume

                        elts = DateTime.Now - BS.pauseflag;
                        
                        BS.status = Profile.BotStatus.stop;
                        break;


                    case Profile.BotStatus._starting:       //Pre-Start

                        TimeSpan stime = (CurentProfile.WorkPlan.workTime - (DateTime.Now - BS.startTime));

                        dummyStart = true;
                        
                        ((Label)GetControlByName("timer_" + (i + 1))).ForeColor = Color.Green;

                        BS.status = Profile.BotStatus.running;
                        break;


                    case Profile.BotStatus.running:         //Started
                        
                        elts = DateTime.Now - BS.startTime;

                        ((Label)GetControlByName("timer_" + (i + 1))).Text = string.Format("{0:0}:{1:00}:{2:00}:{3:00}", elts.Days, elts.Hours, elts.Minutes, elts.Seconds);

                        break;
                }
                DummyBotStart[i] = BS;
            }
        }

        #endregion

        

        #region UI START/STOP/SAVE

        private void Slot_UI_Switcher(bool show = true)
        {
            for (int i = 1; i <= CurentProfile.WorkPlan.Schedule.Count; i++)
            {
                ((Button)GetControlByName("bt_set_" + i)).Visible = show;
                ((Label)GetControlByName("lb_set_" + i)).Visible = show;

                ((Label)GetControlByName("botCharLabel_" + i)).Visible = !show;

                ((Label)GetControlByName("timer_" + i)).Visible = !show;
                ((Button)GetControlByName("bt_bot_min_" + i)).Visible = !show;
                ((Button)GetControlByName("bt_bot_norm_" + i)).Visible = !show;

            }
            for (int i = 8; i > CurentProfile.WorkPlan.Schedule.Count; i--)
            {
                ((Button)GetControlByName("bt_set_" + i)).Visible = !show;
                ((Label)GetControlByName("lb_set_" + i)).Visible = !show;

                ((Label)GetControlByName("botCharLabel_" + i)).Visible = show;

                ((Label)GetControlByName("timer_" + i)).Visible = show;
                ((Button)GetControlByName("bt_bot_min_" + i)).Visible = show;
                ((Button)GetControlByName("bt_bot_norm_" + i)).Visible = show;
            }
        }


        private void bt_run_Click(object sender, EventArgs e)
        {
            #region Registry clean
            /*
            DialogResult dr = MessageBox.Show("Clear Blizz ID?\r\n\r\n Thas may lead to BNet security check... Which means you must be answer on secret question on login in game process.", "BlizzNull", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2, MessageBoxOptions.ServiceNotification);
            if (dr == System.Windows.Forms.DialogResult.Yes)
            {
                
                try
                {
                    RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\Blizzard Entertainment\Battle.net\");
                    foreach (string sValue in key.GetValueNames()) key.DeleteValue(sValue);
                    key.DeleteSubKey("Identity");
                }
                catch { }
            }
            //*/
            #endregion

            firstStart = true;

            Settings.Default.StartDate = DateTime.Now - new TimeSpan(track_span.Value,0,0);

            GenerateSchedule(Settings.Default.StartDate);
            SaveProfile();
            
            Slot_UI_Switcher(false);
            SetBotNames();

            bt_run.Visible = false;
            bt_stop.Visible = true;
            bt_save.Visible = false;

            ts_panel.Enabled = false;

            cb_step.Enabled = false;
            CB_Profile.Enabled = false;
            BT_ProfileBrowse.Enabled = false;
            bt_Clear.Enabled = false;
            
            sw.Reset();
            sw.Start();

            Worker.RunWorker(logbox, Log);

            idleCount = 0;

            Program.StartHook();
        }

        private void bt_stop_Click(object sender, EventArgs e)
        {
            //DialogResult dr = MessageBox.Show("Terminate all runing Bots?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
            //if (dr == System.Windows.Forms.DialogResult.Yes) 
                DiRunTime.StopAllSlots();

            bt_run.Visible = true;
            bt_stop.Visible = false;
            bt_save.Visible = true;

            ts_panel.Enabled = true;

            cb_step.Enabled = true;
            CB_Profile.Enabled = true;
            BT_ProfileBrowse.Enabled = true;
            bt_Clear.Enabled = true;

            Slot_UI_Switcher(true);


            sw.Stop();
            delayTimer.Stop();

            Program.StopHook();
        }


        private void bt_save_Click(object sender, EventArgs e)
        {
            SaveProfile(true);
        }


        private void timer_Tick(object sender, EventArgs e)
        {
            curtime.Text = string.Format("Time {0}", DateTime.Now.ToString("HH:mm:ss"));

            if (sw.IsRunning)
            {
                if (SpanTimer.IsRunning) SpanTimer.Stop();
                Scheduler();
            }

            if (SpanTimer.IsRunning)
            {
                DummyBotStart = CurentProfile.WorkPlan.Schedule;
                DummyScheduler();
                if (SpanTimer.Elapsed.TotalSeconds > 10)
                {
                    Slot_UI_Switcher(true);
                    SpanTimer.Stop();
                }
            }
        }

        #endregion



        #region UI SLOTS

        private void Setup_Click(object sndr, EventArgs e)
        {
            Button sender = (Button)sndr;
            int pos = Convert.ToInt16(sender.Name.Substring(7, 1));
            
            using (BotSetupForm bsf = new BotSetupForm())
            {
                bsf.CurentBot = CurentProfile.Bots[pos - 1];
                bsf.ShowDialog();
                if (bsf.DialogResult == System.Windows.Forms.DialogResult.OK)
                {
                    CurentProfile.Bots[pos - 1] = bsf.CurentBot;
                    CheBotSlots();
                }
                else CheBotSlots();
            }
        }

        public void CheBotSlots()
        {
            int count = CurentProfile.WorkPlan.Schedule.Count;

            bool startReady = true;
            for (int i = 0; i < count; i++)
            {
                Profile.BotProfile bp = CurentProfile.Bots[i];
                bp.ready = true;

                if (bp.bnet == null || bp.bnet.Length < 3) bp.ready = false;
                if (bp.d3_path == null || bp.d3_path.Length < 3) bp.ready = false;
                if (bp.db_key == null || bp.db_key.Length < 3) bp.ready = false;
                if (bp.db_path == null || bp.db_path.Length < 3) bp.ready = false;
                if (bp.db_routine == null || bp.db_routine.Length < 3) bp.ready = false;
                if (bp.pass == null || bp.pass.Length < 3) bp.ready = false;

                if (count > i && !bp.ready)
                {
                    startReady = false;
                    ((Label)GetControlByName("lb_set_" + (i + 1))).Text = "Unset";
                    ((Label)GetControlByName("lb_set_" + (i + 1))).ForeColor = Color.Red;
                }
                else
                {
                    ((Label)GetControlByName("lb_set_" + (i + 1))).Text = "Set";
                    ((Label)GetControlByName("lb_set_" + (i + 1))).ForeColor = Color.Green;
                }
                CurentProfile.Bots[i] = bp;
            }
            if (!startReady) bt_run.Enabled = false;
            else
            {
                bt_run.Enabled = true;
                SaveProfile();
            }
        }

        #endregion



        #region LOG

        private static ConcurrentQueue<string> LogQueue = new ConcurrentQueue<string>();
                        
        public List<string> Log(string text, bool ext = false)
        {
            #region check on empty
            if (LastLogSMG != text) LastLogSMG = text;
            else return new List<string>();
            #endregion

            #region Split text
            string[] splitMsg = null;
            try
            {
                splitMsg = Regex.Split(text, @"(\|#\|)");
            }
            catch { }
            #endregion

            DateTime dt = DateTime.Now;

            #region Check file
            string path = Application.StartupPath;
            if (!Directory.Exists(path + "\\log")) Directory.CreateDirectory(path + "\\log");

            FileInfo logfile = null;
            string filePath = string.Format("{0}\\log\\{1:00}-{2:00}-{3:0000}_", path, dt.Day, dt.Month, dt.Year);

            for (int i = 0; i < 100; i++)
            {
                logfile = new FileInfo(filePath + i + ".txt");
                if (!File.Exists(logfile.DirectoryName + @"\" + logfile.Name)) break;
                else if (logfile.Length < 1048576) break; // 1Mb
            }
            #endregion

            StreamWriter sw = logfile.AppendText();

            List<string> MsgList = new List<string>();
            foreach (string ss in splitMsg)
            {
                if (ss != "|#|" && ss.Length > 0)
                {
                    string msg = string.Format("{0:00}:{1:00}:{2:00}:{3:000}]  {4}",
                        dt.Hour, dt.Minute, dt.Second, dt.Millisecond, ss);

                    sw.WriteLine(string.Format("[{0:00}.{1:00}.{2:0000} {3}",
                        dt.Day, dt.Month, dt.Year, msg));

                    MsgList.Add(string.Format("[{0}\r\n", msg));
                }
            }
            sw.Close();
            sw.Dispose();

            tb_logfile.Text = logfile.FullName;

            if (logbox.Text.Length >= 100000) logbox.Clear();
            if (ext) return MsgList;
            else foreach (string ss in MsgList)
            {
                logbox.AppendText(ss);
            }

            return null;
        }
        #endregion



        #region UTILITES

        public Control GetControlByName(string Name, Control.ControlCollection sub = null)
        {
            foreach (Control c in this.Controls)
            {
                if (c.Name.StartsWith("pan"))
                    foreach (Control cp in c.Controls)
                        if (cp.Name == Name)
                            return cp;
                if (c.Name == Name)
                    return c;
            }
            return null;
        }

        #endregion
               
    }

}
